package cn.okcmd.nio;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;

/**
 * create by caoqg on 2021/7/26
 * 功能说明:测试nioserver
 */
@Slf4j
public class TestServer {

    private static Selector selector=null;
    public static void main(String[] args) throws IOException {
        selector = Selector.open();
        ServerSocketChannel ssc = ServerSocketChannel.open();
        ssc.socket().bind(new InetSocketAddress(8888),1024);
        ssc.configureBlocking(false);
        ssc.register(selector,SelectionKey.OP_ACCEPT);
        while (true){
            log.info("当前server wait data");
            int scNum = selector.select();
            if(scNum<1){
                continue;
            }
            Iterator<SelectionKey> it = selector.selectedKeys().iterator();
            while (it.hasNext()){
                SelectionKey next = it.next();
                it.remove();
                handleKey(next);
            }
        }
    }

    private static void handleKey(SelectionKey next) throws IOException {
        if(next.isAcceptable()){
            ServerSocketChannel ssc = ((ServerSocketChannel) next.channel());
            SocketChannel sc = ssc.accept();
            sc.configureBlocking(false);
            sc.register(selector, SelectionKey.OP_READ);
            doWrite(sc, prefix);
        }
        if(next.isReadable()){
            SocketChannel sc = (SocketChannel) next.channel();
            ByteBuffer buf = ByteBuffer.allocate(1024);
            int read = sc.read(buf);
            if(read>0){
                buf.flip();
                byte[] bytes = new byte[buf.remaining()];
                buf.get(bytes);
                String body = new String(bytes, "UTF-8");
                log.info("read body:{}", body);
                parseCmd(sc, body);
            } else if(read<0){
                next.cancel();
                sc.close();
            } else {
                //todo nothing for read 0 byte;
            }
        }
    }

    private static String prefix="okcmd:";

    private static void parseCmd(SocketChannel sc,String reqBody) throws IOException {
        String cmd = reqBody.trim();
        if(cmd.length()==0){
            doWrite(sc, prefix);
        } else if("ip".equalsIgnoreCase(cmd)){
            doWrite(sc,sc.getRemoteAddress().toString()+"\n");
            doWrite(sc, prefix);
        } else if("exit".equalsIgnoreCase(cmd)||"q".equalsIgnoreCase(cmd)){
            doWrite(sc,"bye\n");
            sc.close();
        } else {
            doWrite(sc,"unknown cmd["+cmd+"]\n");
            doWrite(sc,prefix);
        }

    }

    private static void doWrite(SocketChannel sc, String resp) throws IOException {
        byte[] bytes = resp.getBytes();
        ByteBuffer buf = ByteBuffer.allocate(bytes.length);
        buf.put(bytes);
        buf.flip();
        sc.write(buf);

    }
}
